package com.zxs.order.service.impl;

import client.ProductClient;
import com.zxs.order.mapper.OrderMapper;
import com.zxs.order.service.OrderService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import parm.OrderParam;
import parm.PageParam;
import parm.ProductIdParam;
import parm.ProductIdsParam;
import pojo.*;
import to.OrderToProduct;
import utils.R;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zxs
 * *8 22:33
 */
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Autowired
    private ProductClient productClient;

    /**
     * 消息队列发送
     */
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private OrderMapper orderMapper;

    /**
     * 订单保存业务
     * 1. 将购物车数据转换为订单数据
     * 2. 进行订单的批量插入
     * 3. 商品库存和销量也需要变动，使用异步消息rabbitMq
     * 4. 购物车里也需要修改数量
     * <p>
     * 库存和购物车使用mq异步,避免分布式事务!
     *
     * @param orderParam
     * @return
     */
    @Transactional //添加事务
    @Override
    public R save(OrderParam orderParam) {





        //购物车商品id集合
         List<Integer> cartProductIds = new ArrayList<Integer>();


        //修改清空购物车的参数
        List<Integer> cartIds = new ArrayList<Integer>();
        //修改批量插入数据库的参数
        List<Order> orderList = new ArrayList<>();
        //商品修改库存参数集合
        List<OrderToProduct> orderToProductList =
                new ArrayList<>();


        //封装order实体类集合
        //统一生成订单编号和创建时间
        //使用时间戳 + 做订单编号和事件
        Integer userId = orderParam.getUserId();
        List<CartVo> products = orderParam.getProducts();
        Date dNow = new Date( );
        SimpleDateFormat ctime = new SimpleDateFormat ("yyyy-MM-dd hh:mm:ss");
        String ordertime = ctime.format(dNow);
        System.out.println("当前时间为: " + ordertime);
        long orderid = System.currentTimeMillis();

        String orderStrId = Long.toString( orderid);


        for (CartVo cartVo : products) {
            //购物车的id集合
            cartIds.add(cartVo.getId()); //进行购物车订单保存
            /**
             * 下单时判断是否有库存
            */
            cartProductIds.add(cartVo.getProductID());

            //订单信息保存
            Order order = new Order();
            order.setOrderId(orderStrId);
            order.setUserId(userId);
            order.setOrderTime(ordertime);
            order.setProductId(cartVo.getProductID());
            order.setProductNum(cartVo.getNum());
            order.setProductPrice(cartVo.getPrice());
            orderList.add(order); //添加用户信息

            //修改商品信息存储
            OrderToProduct orderToProduct = new OrderToProduct();
            orderToProduct.setProductId(cartVo.getProductID());
            orderToProduct.setProductNum(cartVo.getNum());
            orderToProductList.add(orderToProduct); //添加集合
        }

        /**
         * 下单时判断是否有库存
         */
        for (Integer id : cartProductIds) {
            ProductIdParam productIdParam = new ProductIdParam();
            productIdParam.setProductId(id);
            Product product = productClient.cartDetail(productIdParam);
            System.out.println("product = " + product);
            if (product == null) {
                return R.fail("商品已经被删除，无法添加到购物车");
            }
            if (product.getProductNum() == 0) {
                R fail = R.fail("商品"+product.getProductName()+"库存："+product.getProductNum()+"没有库存了，不能生成该订单");
                fail.setCode("003");
                return fail;
            }
        }




        //订单批量数据插入
        this.saveBatch(orderList); //批量保存

        //修改商品库存 [product-service] [异步通知]
        /**
         *  交换机: topic.ex
         *  routingkey: sub.number
         *  消息: 商品id和减库存数据集合
         */
        rabbitTemplate.convertAndSend("topic.ex", "sub.number", orderToProductList);
        //清空对应购物车数据即可 [注意: 不是清空用户所有的购物车数据] [cart-service] [异步通知]
        /**
         * 交换机:topic.ex
         * routingkey: clear.cart
         * 消息: 要清空的购物车id集合
         */
        rabbitTemplate.convertAndSend("topic.ex", "clear.cart", cartIds);

        R ok = R.ok("订单生成成功!");
        log.info("OrderServiceImpl.save业务结束，结果:{}", ok);
        return ok;
    }

    /**
     * 1.查询订单，有多个，根据用户id查
     * 2. 将订单根据order_id（时间戳）进行分组，使用stream流方便
     * 3. 根据订单id获得全部商品集合，用stream流转成map
     * 4. 挨个将商品对象和user_id封装成前端需要的 ordervo对象返回
     *
     * @param userId
     * @return
     */
    @Override
    public R list(Integer userId) {
        //1.查询订单，有多个，根据用户id查
        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        List<Order> list = list(queryWrapper);
        // 2. 将订单根据order_id（时间戳）进行分组，使用stream流方便
        Map<String, List<Order>> orderMap = list.stream().collect(Collectors.groupingBy(Order::getOrderId));
        // 3. 根据订单id获得全部商品集合，用stream流转成map
        List<Integer> productIds = list.stream().map(Order::getProductId).collect(Collectors.toList());
        // 4 调用productclient 获取商品对象集合
        ProductIdsParam productIdsParam = new ProductIdsParam();
        productIdsParam.setProductIds(productIds);
        List<Product> productList = productClient.cartList(productIdsParam);
        // 5将list集合转成Map，商品对象id作key，对象本身为值
        Map<Integer, Product> productMap = productList.stream().collect(Collectors.toMap(Product::getProductId, v -> v));

        //6 结果封装
        List<List<OrderVo>> result = new ArrayList<>();

        //遍历订单集合
        for (List<Order> orderList : orderMap.values()) {
            //封装每一个订单
            List<OrderVo> orderVoList = new ArrayList<>();

            for (Order order : orderList) {
                //某个订单
                OrderVo orderVo = new OrderVo();
                //给订单加上附加名字和图片
                BeanUtils.copyProperties(order, orderVo);
                //通过订单id获得商品id，然后通过商品id获得名字和图片
                Product product = productMap.get(order.getProductId());
                orderVo.setProductName(product.getProductName());
                orderVo.setProductPicture(product.getProductPicture());
                // 将封装好的订单内容存储到某个订单（一个订单有多个商品）中
                orderVoList.add(orderVo);
            }
            //将所有订单加入订单集合中
            result.add(orderVoList);
        }

        log.info("订单业务", result);

        return R.ok("订单获取成功", result);
    }

    /**
     * 后台返回订单列表
     *
     * @param pageParam
     * @return
     */
    @Override
    public Object adminList(PageParam pageParam) {

        int offset = (pageParam.getCurrentPage() - 1) * pageParam.getPageSize();
        int number = pageParam.getPageSize();

        //查询数量
        Long total = orderMapper.selectCount(null);
        //自定义查询
        List<AdminOrderVo> adminOrderVoList = orderMapper.selectAdminOrders(offset, number);


        return R.ok("查询成功", adminOrderVoList, total);
    }

    @Override
    public R check(Integer productId) {

        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();

        queryWrapper.eq("product_id", productId);

        Long total = orderMapper.selectCount(queryWrapper);

        if (total == 0) {

            return R.ok("订单中不存在要删除的商品!");
        }

        return R.fail("订单中存在要删除的商品,删除失败!");
    }

    /**
     * 根据orderid订单编号删除订单
     */
    @Override
    public R removeByOrderId(String orderId) {
        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_id", orderId);
        int delete = orderMapper.delete(queryWrapper);
        if (delete>0){
            return R.ok("删除订单成功！");
        }
        return R.fail("删除订单失败！");
    }
}
